// 在“缘分搜索”中用于评分、比较的函数
package utils

import (
	"math"
	"math/rand"
	"time"
	"strings"
)

const SMALLEST_AGE = 18
const YOUTH_AGE = 22
const YOUTH_AGE_2ND = 26
const YOUTH_AGE_3RD = 30
const YOUTH_AGE_4TH = 36

func Fix2Scores(A,B *float64) {
	var step float64 = 0.1
	var halfStep float64 = step/2
	if math.Abs(*A-*B) < step {
		if *A > *B {
			*B = *A-step
		} else if *A < *B {
			*A = *B-step
		} //Ignore case A==B
	}
	if *A < step {
		*A += step
	}
	if *B < step {
		*B += step
	}
	fracA := math.Mod(*A,step)
	if *A < 1-step && fracA > halfStep {
		*A += (step-fracA)
	} else {
		*A -= fracA
	}
	fracB := math.Mod(*B,step)
	if *B < 1-step && fracB > halfStep {
		*B += (step-fracB)
	} else {
		*B -= fracB
	}
}

func youthExtra(A int64) float64 {
	if A < SMALLEST_AGE || A > YOUTH_AGE_4TH {
		return 0.0
	} else if A <= YOUTH_AGE {
		return 0.2
	} else if A <= YOUTH_AGE_2ND {
		return 0.15
	} else if A <= YOUTH_AGE_3RD {
		return 0.1
	} else {
		return 0.05
	}
}

func compareAge(A,B int64) float64 {
	diff := math.Abs(float64(A)-float64(B))
	if diff<=1.0 {
		return 0.7+youthExtra(A)
	} else if diff<=2.0 {
		return 0.6+youthExtra(A)
	} else if diff<=4.0 {
		return 0.5+0.8*youthExtra(A)
	} else if diff<=7.0 {
		return 0.4+0.6*youthExtra(A)
	} else if diff<=10.0 {
		return 0.35+0.4*youthExtra(A)
	} else if diff<=15.0 {
		return 0.3+0.2*youthExtra(A)
	} else if diff<=20.0 {
		return 0.25
	} else if diff<=30.0 {
		return 0.2
	} else {
		return 0.1
	}
}

func compareAgeUnix(A,B int64) float64 {
	var daysInOneYear = 365.0
	var Aday float64 = float64(A) / 86400
	var Bday float64 = float64(B) / 86400
	timeA := time.Unix(A,0)
	ageA := int64(GetCurrentAge(timeA))
	diff := math.Abs(Aday-Bday)
	if diff<=0.5*daysInOneYear {
		return 0.75+youthExtra(ageA)
	} else if diff<=1*daysInOneYear {
		return 0.7+youthExtra(ageA)
	} else if diff<=1.5*daysInOneYear {
		return 0.65+youthExtra(ageA)
	} else if diff<=2*daysInOneYear {
		return 0.6+youthExtra(ageA)
	} else if diff<=3*daysInOneYear {
		return 0.55+0.9*youthExtra(ageA)
	} else if diff<=4*daysInOneYear {
		return 0.5+0.8*youthExtra(ageA)
	} else if diff<=5*daysInOneYear {
		return 0.45+0.7*youthExtra(ageA)
	} else if diff<=7*daysInOneYear {
		return 0.4+0.6*youthExtra(ageA)
	} else if diff<=10*daysInOneYear {
		return 0.35+0.4*youthExtra(ageA)
	} else if diff<=15*daysInOneYear {
		return 0.3+0.2*youthExtra(ageA)
	} else if diff<=20*daysInOneYear {
		return 0.25
	} else if diff<=30*daysInOneYear {
		return 0.2
	} else {
		return 0.1
	}
}

// 获得用户A相当于当前用户user的“年龄”分数（单位：年）
func ScoreAge(A,user int64) float64 {
	return compareAge(A,user)
}

// 获得用户A相当于当前用户user的“年龄”分数（单位：Unix秒）
func ScoreAgeUnix(A,user int64) float64 {
	return compareAgeUnix(A,user)
}

func CompareAges(A,B,user int64) (float64,float64) {
	return compareAge(A,user),compareAge(B,user)
}

func CompareAgesUnix(A,B,user int64) (float64,float64) {
	scoreA := compareAgeUnix(A,user)
	scoreB := compareAgeUnix(B,user)
	Fix2Scores(&scoreA,&scoreB)
	return scoreA,scoreB
}

func compareElementsIn2Strings(source,refer string) (int,int) {
	var score int = 0
	sourceSplit := strings.Split(source," ")
	sourceCount := len(sourceSplit)
	for _,elementInsource := range sourceSplit {
		if strings.Contains(refer,elementInsource){
			score++
		}
	}
	return sourceCount,score
}

func compare2StringAttributes(A,B string) float64 {
	countA,matchA := compareElementsIn2Strings(A,B)
	countB,matchB := compareElementsIn2Strings(B,A)
	var scoreA,scoreB float64 = 0.1,0.1
	if countA > 0 {
		pow := math.Pow(2.0,float64(matchA))
		scoreA = (pow-1.0)/pow
	}
	if countB > 0 {
		pow := math.Pow(2.0,float64(matchB))
		scoreB = (pow-1.0)/pow
	}
	return (scoreA+scoreB)/2
}

// 获得用户A相当于当前用户user的“情感状态”“Requir”“爱好”分数
func ScoreStringAttribute(A,user string) float64 {
	return compare2StringAttributes(A,user)
}

func CompareStringAttributes(A,B,user string) (float64,float64) {
	scoreA := compare2StringAttributes(A,user)
	scoreB := compare2StringAttributes(B,user)
	Fix2Scores(&scoreA,&scoreB)
	return scoreA,scoreB
}

// 获得用户A的“颜值”分数（相对于全服最高highest，最高评分0.99）
func ScoreBeauty(A,highest float64) float64 {
	baseMax := highest / 0.99
	scoreA := A / baseMax
	return scoreA
}

func CompareBeauty(A,B,highest float64) (float64,float64) {
	scoreA := ScoreBeauty(A,highest)
	scoreB := ScoreBeauty(B,highest)
	Fix2Scores(&scoreA,&scoreB)
	return scoreA,scoreB
}

// 获得用户A相当于当前用户user的“地域”分数
func ScoreArea(A,user int64) float64 {
	provA := A / 10000
	provU := user / 10000
	cityA := A / 100
	cityU := user / 100
	if cityA==cityU {
		return 0.8
	} else if provA==provU {
		return 0.7
	} else {
		return 0.5
	}
}

// 对于未实现的评分，返回[0.5,1)之间的随机数
func GetRandomFloat() float64 {
	num := rand.Float64()
	return num/2+0.5
}